/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
 */

import { ModulePathInfoIml } from '../../common/iml/module-path-info-iml.js';
import { ArkTSVersionConst } from '../../const/common-const.js';
import { ModuleTaskService } from '../../tasks/service/module-task-service.js';
import { TargetTaskService } from '../../tasks/service/target-task-service.js';
import { EvolutionService } from './evolution-service.js';

export class ServiceLocator {
  private static targetService: Map<ProductModuleTargetRelationKey, TargetTaskService> = new Map();
  private static moduleService: Map<string, ModuleTaskService> = new Map();
  private static mainModuleService: ModuleTaskService;
  private static modulePathInfoService: Map<ProductModuleTargetRelationKey, ModulePathInfoIml> = new Map();
  private static moduleLanuageMap: Map<string, string> = new Map();
  private static evolutionService: EvolutionService = new EvolutionService();

  static registerTargetService(productName: string, moduleName: string, targetName: string, service: TargetTaskService): void {
    ServiceLocator.targetService.set({productName, moduleName, targetName}, service);
    ServiceLocator.moduleLanuageMap.set(moduleName, service.getSelfArkTSVersion());
  }

  static registerModuleTaskService(moduleName: string, service: ModuleTaskService): void {
    ServiceLocator.moduleService.set(moduleName, service);
  }

  static registerMainModuleTaskService(service: ModuleTaskService): void {
    if (!ServiceLocator.mainModuleService) {
      ServiceLocator.mainModuleService = service;
    }
  }

  static registerModulePathInfoService(productName: string, moduleName: string, targetName: string, service: ModulePathInfoIml): void {
    ServiceLocator.modulePathInfoService.set({productName, moduleName, targetName}, service);
  }

  static getTargetServiceByProductAndModule(productName: string, moduleName: string): TargetTaskService | undefined {
    return ServiceLocator.getServiceProductModuleTargetRelationKey(
      {
        productName: productName,
        moduleName: moduleName,
        targetName: undefined
      },
      ServiceLocator.targetService
    );
  }

  static getTargetServiceByModuleAndTarget(moduleName: string, targetName: string): TargetTaskService | undefined {
    return ServiceLocator.getServiceProductModuleTargetRelationKey(
      {
        productName: undefined,
        moduleName: moduleName,
        targetName: targetName
      },
      ServiceLocator.targetService
    );
  }

  static getModulePathInfoServiceByProductAndModule(productName: string, moduleName: string): ModulePathInfoIml | undefined {
    return ServiceLocator.getServiceProductModuleTargetRelationKey(
      {
        productName: productName,
        moduleName: moduleName,
        targetName: undefined
      },
      ServiceLocator.modulePathInfoService
    );
  }

  static getModulePathInfoServiceByModuleAndTarget(moduleName: string, targetName: string): ModulePathInfoIml | undefined {
    return ServiceLocator.getServiceProductModuleTargetRelationKey(
      {
        productName: undefined,
        moduleName: moduleName,
        targetName: targetName
      },
      ServiceLocator.modulePathInfoService
    );
  }

  static getModuleLanuage(moduleName: string): string {
    return ServiceLocator.moduleLanuageMap.get(moduleName) ?? ArkTSVersionConst.DEFAULT;
  }

  static getModuleLanuageMap(): Map<string, string> {
    return ServiceLocator.moduleLanuageMap;
  }

  static getModuleTaskService(moduleName: string): ModuleTaskService | undefined {
    return ServiceLocator.moduleService.get(moduleName);
  }

  static getEvolutionService(): EvolutionService {
    return ServiceLocator.evolutionService;
  }

  private static getServiceProductModuleTargetRelationKey<T>(
    key: ProductModuleTargetRelationKey,
    map: Map<ProductModuleTargetRelationKey, T>
  ): T | undefined {

    for (const mapk of map.keys()) {
      if (mapk.moduleName !== key.moduleName) {
        continue;
      }

      if (key.productName && mapk.productName === key.productName) {
        return map.get(mapk);
      }

      if (key.targetName && mapk.targetName === key.targetName) {
        return map.get(mapk);
      }
    }
    return undefined;
  }
}

export type ProductModuleTargetRelationKey = {
  productName?: string;
  moduleName: string;
  targetName?: string;
}